/*
 * @Author: DaTree
 * @Date: 2021-09-03 22:29:28
 * @LastEditTime: 2021-09-07 15:40:59
 * @LastEditors: DaTree
 * @Description: DaTreeEdit
 * @FilePath: \demo_services\server.js
 * 天将降大任于是人也，必先苦其心志，劳其筋骨，饿其体肤，空乏其身，行拂乱其所为。 ——《孟子•告子下》
 * Copyright 2021 DaTree
 */
const http = require("http");
const url = require("url");
const fs = require("fs");
const log = require("./log").log;
const serveFileDir = "";
let serveFilePath = "";
/**
 * 设置静态文件 html、js等的路径
 * @param {*} p 
 */
const setServeFilePath = (p) => {
  serveFilePath = p;
}
exports.serveFilePath = setServeFilePath;
/**
 * 创建一个处理程序，以基于路径名称来路由请求。
 * @param {*} handle 
 * @param {*} port 
 */
const start = (handle, port) => {
  const onRequest = (req, res) => {
    const urldata = url.parse(req.url, true);
    const pathname = urldata.pathname;
    const info = { res, query: urldata.query, postData: "" };
    log("Request for " + pathname + " received");
    req.setEncoding("utf8");
    req.addListener("data", function (postDataChunk) {
      info.postData += postDataChunk
      log("接收到数据 '" + postDataChunk + "'.")
    })
    req.addListener("end", function () {
      route(handle, pathname, info);
    })
    // 之前是直接路由，现在由于要分段接收数据，改用监听end事件处理。
    // route(handle, pathname, info);
  }
  http.createServer(onRequest).listen(port);
  log("服务已启动成功，端口：" + port);
}
exports.start = start;
const route = (handle, pathname, info) => {
  log("请求路径：" + pathname);
  const filepath = createFilePath(pathname);
  log('请求静态资源：' + filepath);
  fs.stat(filepath, (err, stats) => {
    if (!err && stats.isFile()) {
      //处理文件
      serveFile(filepath, info);
    } else {
      //必须为自定义路径
      handleCustom(handle, pathname, info);
    }
  })
}
/**
 * 创建文件路径
 * @param {*} pathname 
 * @returns 
 */
const createFilePath = (pathname) => {
  const commponents = pathname.substr(1).split("/");
  const filtered = new Array();
  let temp = null;
  for (let i = 0; i < commponents.length; i++) {
    temp = commponents[i];
    if (temp == '..') {
      continue;
    }
    if (temp == "") {
      continue;
    }
    temp = temp.replace(/~/g, '');
    filtered.push(temp)
  }
  return (serveFilePath + "/" + filtered.join("/"))
}


const contentType = (filepath) => {
  const index = filepath.lastIndexOf('.');
  if (index !== -1) {
    switch (filepath.substr(index + 1)) {
      case "html": return "text/html";
      case "js": return "application/javascript";
      case "css": return "text/css";
      case "txt": return "text/plain";

      default:
        return "text/html";
    }
  }
  return "text/html;";
}
const handleCustom = (handle, pathname, info) => {
  if (typeof handle[pathname] === 'function') {
    handle[pathname](info);
  } else {
    noHandleError(pathname, info.res);
  }
}
const noHandleError = (pathname, res) => {
  log("未找到文件: " + pathname)
  res.writeHead(404, { "Content-Type": "text/plain" });
  res.write("404 Page Not Found");
  res.end();
}

function addQuery (str, q) {
  if (q) {
    return str.replace("<script></script>", "<script>var queryparams=" + JSON.stringify(q) + "</script>")
  } else {
    return str;
  }
}

/**
 * 打开指定文件、读取其中内容并将这些内容发送至客户端
 * @param {*} filepath 
 * @param {*} info 
 */
const serveFile = (filepath, info) => {
  const res = info.res;
  const query = info.query;
  log("Serving file " + filepath);
  fs.open(filepath, 'r', (err, fd) => {
    if (err) {
      log(err.message);
      noHandleError(filepath, res);
      return;
    }
    const readBuffer = new Buffer(1024 * 1024 * 2);
    fs.read(fd, readBuffer, 0, 1024 * 1024 * 2, 0, (err, readBytes) => {
      if (err) {
        log(err.message);
        fs.close(fd);
        noHandleError(filepath, res);
        return;
      }
      log('just read ' + readBytes + " bytes");
      if (readBytes > 0) {
        res.writeHead(200, { "Content-Type": contentType(filepath) });
        res.write(addQuery(readBuffer.toString('utf8', 0, readBytes), query));
        res.end();
      }
    })
  })
}